package com.zx.repository.impl;

import com.zx.model.Course;
import com.zx.repository.CourseCustomRepository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * description: 自定义接口实现 <br>
 * create: 2024-10-25 12:59
 * </p>
 *
 * @author zhou  xun
 */
@Repository
public class CourseRepositoryImpl implements CourseCustomRepository {

    // 注入EntityManager实例，用于执行JPA查询
    private final EntityManager entityManager;

    @Autowired
    public CourseRepositoryImpl(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    /**
     * 根据课程查询课程数量
     *
     * @param course 查询条件
     * @return 记录总数
     * @author zhou  xun
     * @since 2024-10-25
     */
    @Override
    public Long countByCourse(Course course) {
        // 获取CriteriaBuilder实例，用于构建查询
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();

        // 创建一个返回Long类型的CriteriaQuery
        CriteriaQuery<Long> criteriaQuery = cb.createQuery(Long.class);

        // 从Course实体类创建一个根节点，用于后续的查询构建
        Root<Course> courseRoot = criteriaQuery.from(Course.class);

        // 构建查询条件
        Predicate[] predicates = buildPredicates(courseRoot, course, cb);

        // 设置查询的SELECT子句，统计满足条件的记录数
        criteriaQuery.select(cb.count(courseRoot)).where(predicates);

        // 创建一个TypedQuery，用于执行具体的查询
        TypedQuery<Long> typedQuery = entityManager.createQuery(criteriaQuery);

        // 执行查询并返回结果
        return typedQuery.getSingleResult();
    }

    /**
     * 按条件分页查询课程
     *
     * @param course   查询条件
     * @param pageable 分页对象
     * @return 课程分页结果
     * @author zhou  xun
     * @since 2024-10-25
     */
    @Override
    public Page<Course> courseRepositoryByPage(Course course, Pageable pageable) {
        // 获取CriteriaBuilder实例，用于构建查询
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();

        // 创建一个返回Course类型的CriteriaQuery
        CriteriaQuery<Course> criteriaQuery = cb.createQuery(Course.class);

        // 从Course实体类创建一个根节点，用于后续的查询构建
        Root<Course> courseRoot = criteriaQuery.from(Course.class);

        // 构建查询条件
        Predicate[] predicates = buildPredicates(courseRoot, course, cb);

        // 设置查询的WHERE子句
        criteriaQuery.where(predicates);

        // 创建一个TypedQuery，用于执行具体的查询
        TypedQuery<Course> typedQuery = entityManager.createQuery(criteriaQuery);

        // 设置查询的起始位置和结果数量限制
        typedQuery.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
        typedQuery.setMaxResults(pageable.getPageSize());

        // 执行查询并获取结果列表
        List<Course> content = typedQuery.getResultList();

        // 计算总记录数
        // 调用countByCourse方法获取总数
        Long total = countByCourse(course);

        // 创建并返回PageImpl对象，封装分页结果
        return new PageImpl<>(content, pageable, total);
    }

    /**
     * 构建查询条件
     *
     * @param courseRoot 根节点
     * @param course     查询条件
     * @param cb         CriteriaBuilder实例
     * @return 查询条件数组
     */
    private Predicate[] buildPredicates(Root<Course> courseRoot, Course course, CriteriaBuilder cb) {
        // 创建一个列表来存储查询条件
        List<Predicate> predicates = new ArrayList<>();

        // 如果查询条件的ID不为空，则添加一个等于条件
        if (course.getId() != null) {
            predicates.add(cb.equal(courseRoot.get("id"), course.getId()));
        }

        // 如果查询条件的课程名不为空且非空字符串，则添加一个等于条件
        if (course.getCourseName() != null && !course.getCourseName().trim().isEmpty()) {
            //注意:courseName 取的是实体属性名称，不是数据库字段名称
            predicates.add(cb.equal(courseRoot.get("courseName"), course.getCourseName()));
        }

        // 如果查询条件的课程类型不为空，则添加一个等于条件
        if (course.getCourseType() != null) {
            predicates.add(cb.equal(courseRoot.get("courseType"), course.getCourseType()));
        }

        // 如果查询条件的课程图标不为空且非空字符串，则添加一个等于条件
        if (course.getCourseIcon() != null && !course.getCourseIcon().trim().isEmpty()) {
            predicates.add(cb.equal(courseRoot.get("courseIcon"), course.getCourseIcon()));
        }

        // 如果查询条件的课程介绍不为空且非空字符串，则添加一个等于条件
        if (course.getCourseIntro() != null && !course.getCourseIntro().trim().isEmpty()) {
            predicates.add(cb.equal(courseRoot.get("courseIntro"), course.getCourseIntro()));
        }

        // 如果查询条件的创建时间不为空，则添加一个等于条件
        if (course.getCreateTime() != null) {
            predicates.add(cb.equal(courseRoot.get("createTime"), course.getCreateTime()));
        }

        // 如果查询条件的更新时间不为空，则添加一个等于条件
        if (course.getUpdateTime() != null) {
            predicates.add(cb.equal(courseRoot.get("updateTime"), course.getUpdateTime()));
        }

        // 将列表转换为数组并返回
        return predicates.toArray(new Predicate[0]);
    }
}